/* eslint-disable default-case */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import {
  computed,
  defineComponent,
  onMounted,
  PropType,
  ref,
  Ref,
  watch,
} from 'vue';
import { useNamespace } from '@ibiz-template/vue3-util';
import { IPanelRawItem } from '@ibiz/model-core';
import { createUUID } from 'qx-util';
import { GroupSearchController } from './group-search.controller';
import { ITreeNode } from './interface';
import {
  FilterSearchBarController,
  GroupType,
  IGroupData,
} from '../filter-search-bar';
import './group-search.scss';

export const GroupSearch = defineComponent({
  name: 'IBizGroupSearch',
  props: {
    modelData: {
      type: Object as PropType<IPanelRawItem>,
      required: true,
    },
    controller: {
      type: GroupSearchController,
      required: true,
    },
  },
  setup(prop) {
    const ns = useNamespace('group-search');
    const c = prop.controller;

    const visible: Ref<boolean> = ref(false);
    const query: Ref<string> = ref('');
    const treeRef: Ref<IData | null> = ref(null);
    const searchBar: Ref<FilterSearchBarController | null> = ref(null);
    const dropdownRef: Ref<IData | null> = ref(null);
    const collect: ITreeNode = {
      caption: '收藏',
      id: createUUID(),
      type: GroupType.COLLECT,
    };
    const rootNodes: ITreeNode[] = [
      {
        caption: '我创建的',
        id: createUUID(),
        children: [],
        type: GroupType.PRIVATE,
      },
      {
        caption: '公共视图',
        id: createUUID(),
        children: [],
        type: GroupType.PUBLIC,
      },
    ];

    const group = computed(() => {
      return searchBar.value?.state.groupFilter;
    });

    const tree = computed(() => {
      let nodes: IData[] = [];
      const collects = group.value?.filter(g => g.collect);
      if (collects && collects.length > 0) {
        nodes.push({
          ...collect,
        });
        nodes = nodes.concat(collects);
      }
      nodes = nodes.concat([...rootNodes]);
      nodes.forEach(node => {
        if (node.type && node.children) {
          node.children =
            group.value?.filter(s => s.groupType === node.type) || [];
        }
      });
      return nodes;
    });

    watch(
      () => query.value,
      val => {
        treeRef.value?.filter(val);
      },
    );

    onMounted(() => {
      searchBar.value = c.searchBar;
    });

    const onVisibleChange = (state: boolean) => {
      visible.value = state;
      if (!visible.value) {
        query.value = '';
      }
    };

    const onFilterNode = (value: string, data: IData) => {
      if (!value) return true;
      return data.caption.includes(value);
    };

    const onNodeClick = (item: IData) => {
      if (!item.type) {
        c.searchBar?.onGroupClick(item as IGroupData);
        dropdownRef.value?.handleClose();
      }
    };

    const onCollect = async (item: IData, evt: MouseEvent) => {
      evt.stopPropagation();
      await c.searchBar?.handleGroupCollect(item as IGroupData, !item.collect);
    };

    const onCommand = (actionName: string) => {
      switch (actionName) {
        case 'onNewGroup':
          c.searchBar?._evt.emit('onNewGroup', undefined);
          break;
      }
    };

    const renderSelectNode = (node: IData, data: IData) => {
      return (
        <div class={ns.em('node', 'content')}>
          {!data.collect || (data.collect && node.level === 1) ? (
            <ion-icon
              name='checkmark-outline'
              class={[
                ns.em('node', 'icon-selected'),
                ns.is(
                  'selected',
                  c.searchBar?.state.selectGroup?.name === data.name,
                ),
              ]}
            ></ion-icon>
          ) : null}
          <span class={ns.em('node', 'caption')}>{data.caption}</span>
          {data.collect ? (
            <ion-icon
              name='star'
              class={ns.em('node', 'icon-star')}
              onClick={(evt: MouseEvent) => onCollect(data, evt)}
            ></ion-icon>
          ) : (
            <ion-icon
              name='star-outline'
              class={ns.em('node', 'icon-star')}
              onClick={(evt: MouseEvent) => onCollect(data, evt)}
            ></ion-icon>
          )}
        </div>
      );
    };

    const renderNode = (node: IData, data: IData) => {
      return (
        <div class={[ns.e('node'), ns.em('node', `level${node.level}`)]}>
          {data.type ? (
            <span class={ns.em('node', 'caption')}>{data.caption}</span>
          ) : (
            renderSelectNode(node, data)
          )}
        </div>
      );
    };

    return {
      c,
      ns,
      query,
      tree,
      visible,
      treeRef,
      dropdownRef,
      onCommand,
      onNodeClick,
      onFilterNode,
      onVisibleChange,
      renderNode,
      onCollect,
    };
  },
  render() {
    if ((ibiz.env as IData).simplemode) {
      return null;
    }
    return (
      <div
        class={[
          this.ns.b(),
          this.ns.m(this.modelData.id),
          ...this.controller.containerClass,
        ]}
      >
        <el-dropdown
          ref='dropdownRef'
          trigger='click'
          popper-class={this.ns.b()}
          onCommand={this.onCommand}
          onVisibleChange={this.onVisibleChange}
        >
          {{
            default: () => (
              <el-button class={this.ns.e('button')}>
                <span class={this.ns.e('caption')}>
                  {this.c.searchBar?.state.selectGroup?.caption}
                </span>
                {this.visible ? (
                  <ion-icon name='chevron-up-outline'></ion-icon>
                ) : (
                  <ion-icon name='chevron-down-outline'></ion-icon>
                )}
              </el-button>
            ),
            dropdown: () => (
              <el-dropdown-menu>
                <el-input v-model={this.query} clearable placeholder='搜索'>
                  {{
                    prefix: () => <ion-icon name='search-outline'></ion-icon>,
                  }}
                </el-input>
                <el-tree
                  ref='treeRef'
                  data={this.tree}
                  props={{ label: 'caption' }}
                  node-key='id'
                  indent={0}
                  default-expand-all
                  filter-node-method={this.onFilterNode}
                  onNodeClick={this.onNodeClick}
                >
                  {{
                    default: ({ data, node }: { node: IData; data: IData }) => {
                      return this.renderNode(node, data);
                    },
                    empty: () => (
                      <iBizNoData text='没有找到匹配项'></iBizNoData>
                    ),
                  }}
                </el-tree>
                <el-dropdown-item command='onNewGroup'>
                  新建分组
                </el-dropdown-item>
              </el-dropdown-menu>
            ),
          }}
        </el-dropdown>
      </div>
    );
  },
});
